﻿# -*- coding: utf-8 -*-
from model import *
from google.appengine.api import urlfetch

class Core():
    MAX_FETCH = 1000
    MAX_NAME_NUM = 100
    MAX_REMARK_NUM = 100

    mh = None
    request = None
    method = None
    path = None

    testStr = None
    action = None
    actionPath = None
    clipboardActionPath = None
    clipboardField = None
    currentSort = None
    currentSortId = None
    navigationLinks = None
    sorts = None
    fields = None

    def __init__(self, mh):
        self.mh = mh
        self.request = self.mh.request
        self.method = self.request.method
        self.path = self.request.path

        self.testStr = None
        self.action = None
        self.actionPath = None
        self.clipboardActionPath = None
        self.clipboardField = {}
        self.currentSortId = self.request.get('currentSortId')
        if self.currentSortId != '':
            self.currentSort = Sort.get_by_id(int(self.currentSortId)).name
        self.navigationLinks = []
        self.sorts = []
        self.fields = []

    def prepareData(self):
        if self.method == 'GET':
            self.prepareGetData()
        else:
            self.postData()
        return self.fillPageData()

    def prepareGetData(self):
        if self.path == '/':
            self.action = 'show_sort'
            self.actionPath = '/add_sort'
            self.clipboardActionPath = '/update_clipboard'
            query = Sort.all()
            if query.count() != 0:
                self.navigationLinks.append({'name':'修改分类', 'path': '/update_sort'})
                self.navigationLinks.append({'name':'刷新', 'path': '/'})
            self.fillSort()
            self.fillClipboardField()
        elif self.path == '/update_sort':
            self.action = 'update_sort'
            self.actionPath = '/update_sort'
            self.navigationLinks.append({'name':'主页', 'path': '/'})
            self.fillSort()
        elif self.path == '/show':
            self.action = 'show_field'
            self.actionPath = '/add_field?currentSortId=' + self.currentSortId
            query = self.getQueryOfFieldOfCurrentSort()
            if query.count() != 0:
                self.navigationLinks.append({'name':'修改字符串', 'path': '/update_field?currentSortId=' + self.currentSortId})
            self.navigationLinks.append({'name':'主页', 'path': '/'})
            self.navigationLinks.append({'name':'刷新', 'path': '/show?currentSortId=' + self.currentSortId})
            self.fillField()
        elif self.path == '/update_field':
            self.action = 'update_field'
            self.actionPath = '/update_field?currentSortId=' + self.currentSortId
            self.navigationLinks.append({'name':'主页', 'path': '/'})
            self.navigationLinks.append({'name':self.currentSort, 'path': '/show?currentSortId=' + self.currentSortId})
            self.fillField()

    def fillClipboardField(self):
        currentSort = self.currentSort
        self.currentSort = None
        fields = self.getFieldsOfCurrentSort()
        if len(fields) > 0:
            self.clipboardField['name'] = fields[0].name
            self.clipboardField['content'] = fields[0].content
            self.clipboardField['remark'] = self.adjustStr(fields[0].remark, self.MAX_REMARK_NUM)
            self.clipboardField['type'] = self.getContentType(fields[0].content)
            self.clipboardField['lineNum'] = self.getContentLineNum(fields[0].content)
        self.currentSort = currentSort

    def fillField(self):
        fields = self.getFieldsOfCurrentSort()
        fields.sort(key = lambda field : field.index)
        for item in fields:
            strType = self.getContentType(item.content)
            remark = self.adjustStr(item.remark, self.MAX_REMARK_NUM)
            lineNum = self.getContentLineNum(item.content)
            item.name = self.adjustStr(item.name, self.MAX_NAME_NUM)
            self.fields.append({'name':item.name, 'content':item.content, 'remark':remark, 'type':strType, 'lineNum':lineNum})

    def getContentLineNum(self, content):
        lineNum = content.count('\n') + 1
        if lineNum > 3:
            lineNum = 3
        return lineNum

    def getContentType(self, content):
        strType = 'str'
        if self.getContentLineNum(content) > 1:
            return strType
        if content.find('http://') > -1 or content.find('https://') > -1:
            strType = 'url'
        return strType

    def adjustStr(self, str, maxNum):
        if str is not None:
            if len(str) > maxNum:
                str = str[0 : maxNum - 3] + '...'
        return str

    def fillSort(self):
        query = Sort.all()
        results = query.fetch(self.MAX_FETCH)
        for result in results:
            result.name = self.adjustStr(result.name, self.MAX_NAME_NUM)
            self.sorts.append({'name':result.name, 'path':'/show?currentSortId=' + str(result.key().id())})

    def postData(self):
        if self.path == '/add_sort':
            self.saveSort(self.request.get('sort'))
            self.mh.redirect('/')
        elif self.path == '/update_sort':
            webSorts = self.request.get_all('sort')
            dataSorts = Sort().all().fetch(len(webSorts))
            for i in range(len(webSorts)):
                self.saveSort(webSorts[i], dataSorts[i], action = 'update')
            self.mh.redirect('/')
        elif self.path == '/add_field':
            self.saveField(self.request.get('content'), self.request.get('name'))
            url = '/show?currentSortId=' + self.currentSortId
            self.mh.redirect(url)
        elif self.path == '/update_field':
            webContents = self.request.get_all('content')
            webNames = self.request.get_all('name')
            webTop = self.request.get('top')
            if webTop != '' and webContents[int(webTop)] == '':
                url = '/show?currentSortId=' + self.currentSortId
                self.mh.redirect(url)
                return
            fields = self.getFieldsOfCurrentSort()
            newIndexs = self.getNewIndex(webTop, fields)
            for i in range(len(webContents)):
                self.saveField(webContents[i], webNames[i], fields[i], newIndexs[i], action = 'update')
            url = '/show?currentSortId=' + self.currentSortId
            self.mh.redirect(url)
        elif self.path == '/update_clipboard':
            self.currentSort = None
            clipboardContent = self.request.get('clipboardContent')
            fields = self.getFieldsOfCurrentSort()
            if clipboardContent == '':
                self.mh.redirect('/')
                return
            if len(fields) == 0:
                self.saveField(clipboardContent)
            else:
                self.saveField(clipboardContent, None, fields[0], action = 'update')
            self.mh.redirect('/')

    def getNewIndex(self, top, fields):
        indexs = []
        for item in fields:
            indexs.append(item.index)
        if top == '' or top == '0':
            return indexs
        top = int(top)
        indexs[top] = 1
        for i in range(top):
            indexs[i] += 1
        return indexs

    def saveSort(self, name, sort = None, action = 'add'):
        if sort is not None and name == '':
            self.currentSort = sort.name
            fields = self.getFieldsOfCurrentSort()
            for item in fields:
                item.delete()
            sort.delete()
            return
        if action == 'add':
            if self.isRepeatSort(name):
                return
            sort = Sort()
            sort.index = self.getCountOfSort()
        if sort.name == name:
            return
        sort.name = name
        sort.put()

    def saveField(self, content, name = None, field = None, newIndex = None, action = 'add'):
        if action != 'add' and (field.index != newIndex and content == ''):
            return
        if field is not None and content == '':
            fields = self.getFieldsOfCurrentSort()
            for i in range(field.index, len(fields)):
                fields[i].index -= 1
                fields[i].put()
            field.delete()
            return
        if action == 'add':
            if content == '':
                return
            field = Field()
            field.index = self.getCountOfFieldOfCurrentSort()
            field.name = name
            field.sort = self.getSortKeyOfCurrentSort()
        if action == 'update':
            updateFlag = False
            if field.content != content:
                field.content = content
                updateFlag = True
            if field.index != newIndex:
                field.index = newIndex
                updateFlag = True
            if field.name != name:
                field.name = name
                updateFlag = True
            if not updateFlag:
                return
        self.handlerContent(field, content)
        field.put()

    def getCountOfSort(self):
        query = Sort.all()
        return query.count() + 1

    def getCountOfFieldOfCurrentSort(self):
        query = self.getQueryOfFieldOfCurrentSort()
        return query.count() + 1

    def getFieldsOfCurrentSort(self):
        query = self.getQueryOfFieldOfCurrentSort()
        fields = query.fetch(self.MAX_FETCH)
        fields.sort(key = lambda field : field.index)
        return fields

    def getQueryOfFieldOfCurrentSort(self):
        sortKey = self.getSortKeyOfCurrentSort()
        query = Field.all()
        query.filter('sort =', sortKey)
        return query

    def getSortKeyOfCurrentSort(self):
        query = Sort.all()
        query.filter('name =', self.currentSort)
        sortKey = query.get()
        return sortKey

    def isRepeatSort(self, str):
        query = Sort.all()
        for item in query.fetch(self.MAX_FETCH):
            if item.name == str:
                return True
        return False

    def handlerContent(self, field, content):
        field.content = self.fixUrl(content)
        if field.content.find('http://') > -1 or field.content.find('https://') > -1:
            title = self.getPageTitle(field.content)
            field.remark = title

    def fixUrl(self, str):
        if self.getContentLineNum(str) > 1:
            return str
        strLower = str.lower()
        strTemp = 'http://'
        if strLower.find(strTemp) > -1:
            str = strTemp + str[len(strTemp) :]
        strTemp = 'https://'
        if strLower.find(strTemp) > -1:
            str = strTemp + str[len(strTemp) :]
        strTemp = '//www.'
        if strLower.find(strTemp) > -1:
            str = str[0 : strLower.find(strTemp)] + strTemp + str[strLower.find(strTemp) + len(strTemp) :]
        if str[0 : 4] == 'www.' and str.rindex('.') > 4:
            str = 'http://' + str
        return str

    def getPageTitle(self, url):
        try:
            result = urlfetch.fetch(url)
            if result.status_code == 200:
                content = ''.join(result.content.lower().split())
            else:
                return None
            if content.find('charset=') > -1:
                pos = content.find('charset=') + len('charset=')
                if content[pos] == '"' or content[pos] == '\'':
                    pos += 1
                    charset = content[pos : content.find(content[pos - 1], pos)]
                else:
                    charset = content[pos : content.find('"', pos)]
            else:
                charset = 'gbk'
        except:
            charset = 'gbk'

        try:
            if content.find('<title>') == -1:
                return None
            pos = content.find('<title>') + len('<title>')
            title = content[pos : content.find('</title>')]
            return title.decode(charset)[0 : 250]
        except:
            return None

    def fillPageData(self):
        pageData = {}
        pageData['testStr'] = self.testStr
        pageData['action'] = self.action
        pageData['actionPath'] = self.actionPath
        pageData['clipboardActionPath'] = self.clipboardActionPath
        pageData['clipboardField'] = self.clipboardField
        pageData['currentSort'] = self.currentSort
        pageData['navigationLinks'] = self.navigationLinks
        pageData['sorts'] = self.sorts
        pageData['fields'] = self.fields
        return pageData